home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / os2 / edm0406i.zip / EDMI4-6.INF (.txt) < prev    next >
OS/2 Help File  |  1996-07-08  |  253KB  |  2,150 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Jul 1996 Title Page ΓòÉΓòÉΓòÉ
  3.  
  4.  
  5.                       Portions copyright (c) by IQPac Inc.
  6.                                 Volume 4, issue 6
  7.  
  8. Microsoft Does it Again 
  9.  
  10. It's like the ole' one-two body punch that you know is coming but can't do 
  11. anything about.  Doesn't it sometimes seem like no one wants to do anything 
  12. about it, though?  Peter Coffee reports in this week's PC Week that Microsoft 
  13. is not going directly to the object-oriented file system in Cairo but will 
  14. instead make constant incremental upgrades to NT to (eventually) achieve this 
  15. goal. 
  16.  
  17. The really scary thing is that they'll get away with it again.  Just like 
  18. they'll get away with the ActiveX confusion that they've created.  According to 
  19. the opinions of the trade press, once the version of Visual Basic is released 
  20. that generates ActiveX controls, no one will remember how bad it really is.  I 
  21. can relate - I had thought Basic was dead and buried until Microsoft 
  22. resurrected it and (worse yet) made it one of the most popular languages in the 
  23. "I'm not really a geek" market. 
  24.  
  25. PC Expo is Here Again 
  26.  
  27. All of this hoopla can only mean one thing (actually, it could mean several, 
  28. but that sounded good so I went with it) - PC Expo is back in town.  I'm 
  29. beginning to wonder if I shouldn't apply for a hotdog vendor's license.  Anyone 
  30. who has attended this show knows what I'm talking about - this is the only week 
  31. when hotdogs on the West Side cost $2.00 each, and that's the bargain price! 
  32.  
  33. The show should be good, though.  There is supposedly a separate section just 
  34. for the Internet and related technologies, which I am looking forward to 
  35. browsing.  Also, who can forget all of the goodies, although the quality has 
  36. been declining in recent years (as I have been told.  I haven't attended the 
  37. past two shows.) 
  38.  
  39. Anyway, if you're planning on being there, send me email and we'll meet 
  40. somehow. 
  41.  
  42. Cast Your Ballots! 
  43.  
  44. Speaking of sending me email, I hope to soon have a working HTML form that you 
  45. can use to vote on your favorite article over the past months.  If I don't have 
  46. it done soon, I will have to revert to email for the ballots.  [sigh] 
  47.  
  48. We have three prizes already generously donated by IBM which will go to the 
  49. winners.  These aren't pledges - I have them here in my "toy room" (still 
  50. shrink-wrapped, I will proudly add).  I will not yet divulge what they are, 
  51. however. 
  52.  
  53. Our First Advertisement 
  54.  
  55. EDM has its first victory!  We are happy to welcome SPG to the (now-growing) 
  56. list of EDM sponsors. 
  57.  
  58. My Absence 
  59.  
  60. I've been absent the past week.  I apologize, but I plead hard drive trouble as 
  61. the cause.  It started last week with the corruption of the "EA DATA . SF" 
  62. file's FAT entry on my boot drive.  This means, for those who haven't picked up 
  63. on it yet, that my desktop was lost totally.  I didn't do anything to cause 
  64. this; it just happened sometime between the time I turned off the computer last 
  65. Sunday and the time I turned it on again the next evening. 
  66.  
  67. The next night, the Boot Manager partition became the active one that was 
  68. booted - a feature I disabled a long time ago.  The partition name was missing, 
  69. too. 
  70.  
  71. That was enough for me.  I booted to the command line, backed everything of 
  72. value up to the ZIP drive that I wrote about a few weeks ago, repartitioned, 
  73. reformatted, and reinstalled.  (Un)fortunately, my version of Warp is the 
  74. original, pre-CONFIG.SYS/AUTOEXEC.BAT bug-fix, red box version that was 
  75. distributed to the press (who subsequently ate it for breakfast), and I didn't 
  76. want to reinstall that monster, so I conveniently used this as an excuse to 
  77. upgrade to Warp Connect.  Oh, and I forgot to make a bootable DOS floppy (I 
  78. need my real-time MIDI recording capabilities), so I just had to buy DOS 7.0. 
  79.  
  80. All-in-all, the day (Wednesday) wasn't so bad. 
  81.  
  82. Voting is On! 
  83.  
  84. Then, on Thursday, I discovered the bug that has been plaguing me since the 
  85. beginning of May; I fixed it and the result is that you are now able to vote 
  86. for your favorite articles.  The winners get big prizes, so cast your vote 
  87. today! 
  88.  
  89. Other changes on the site include the much-overlooked mistake that the Back 
  90. Issues and the Links pages were the same.  Worse yet, I made this mistake 
  91. locally, so I didn't have a backup to fall upon.  (I did have a sword, but 
  92. that's so messy.)  We now have a growing list of links and are always looking 
  93. for more. 
  94.  
  95. The Acknowledgments and Sponsors pages have been combined.  This only makes 
  96. sense. 
  97.  
  98. The Real World 
  99.  
  100. But, enough of us.  What's going on out there? 
  101.  
  102.      Another journalist has the solution to IBM's troubles - "What IBM really 
  103.       needs to do is..."  How many times have you heard this?  I'll finish that 
  104.       sentence by saying that IBM really needs to tell these people to shut up 
  105.       ("or something...huhuhuhuh").  Only when the ambient noise has been 
  106.       eliminated can they concentrate on solving their problems. 
  107.      IBM announces that it's buying Microsoft - just seeing if you're awake. 
  108.       [grin] 
  109.      Merlin gains another feature - Infoworld likened Merlin to the Swiss Army 
  110.       knife, an analogy that is not ill-fitted at all.  IBM announced plans to 
  111.       include Notes Mail with the new version of OS/2, the first beta of which 
  112.       will ship next week.  This new version will not run any custom Notes 
  113.       applications, however. 
  114.  
  115.  Quick!  Everyone Do the Hokey Pokey! 
  116.  
  117.  Blah blah blah.  I suppose it's that "time of the year" again.  Some "high 
  118.  priced consultant to IBM" said, according to Robert X. Cringely, that Merlin 
  119.  better sell well or OS/2 is toast.  I have a very nasty suspicion that I know 
  120.  this person well, especially since he fits that description and is always 
  121.  hooting about how OS/2 is doomed.  He doesn't mind taking their money, 
  122.  however. 
  123.  
  124.  Heh.  Maybe he should become the "people's poet" by quitting his position so 
  125.  that IBM can put an extra dollar or two into the OS/2 coffers. 
  126.  
  127.  "Well, gee, Wally.  Redmond says everyone's moving to NT and this here high 
  128.  priced consultant says that OS/2 is doomed, so I guess, yuck yuck, that we 
  129.  should also do the 'hokey pokey.'" 
  130.  
  131.  That's us.  Just call us "idiot's on a rope." 
  132.  
  133.  OS2Web is Back Up! 
  134.  
  135.  After the "Pe-Perlow Fi-asco" (that even has the proper rhythm), Jeff "Boomer" 
  136.  Bakalchuck (I hope I spelled his name properly) has gotten everything in order 
  137.  and the sight is once again at "full steam ahead."  (Aye, aye, Captain.)  If 
  138.  you haven't visited in a while, the new look will pleasantly surprise you. 
  139.  Stop by at http://www.teamos2.org/os2web. 
  140.  
  141.  From the IBM School of Marketing 
  142.  
  143.  It seems that Rogue Wave took that IBM route when it comes to marketing. 
  144.  "Yessirree, yuck yuck, we'll build a better mousetrap and they'll come a 
  145.  runnin'."  I'll bet that you don't know that Rogue Wave has an OS/2 Java 
  146.  development environment already on the market.  Yeah, neither did we.  We have 
  147.  the name and number of someone at Rogue Wave that we hope to speak with 
  148.  shortly about this.  Look for a "First Looks" on this hopefully coming in an 
  149.  issue soon. 
  150.  
  151.  PC Expo 
  152.  
  153.  I'm really surprised that no one asked me anything about PC Expo.  I daresay 
  154.  that if you weren't there, you didn't care; this would explain the lack of 
  155.  interest.  My beef at the show was to drum up support for EDM/2, including 
  156.  selling advertising space, acquiring software for review, and generally making 
  157.  myself known.  Of course, I could've showed up in a katt outfit, but I didn't 
  158.  want to be too conspicuous. 
  159.  
  160.  "So," you ask me, "what did you see?"  Well, when I wasn't trying to hobnob 
  161.  with the various product managers and such, I did manage to see... 
  162.  
  163.  Merlin 
  164.  
  165.  This was the hottest thing for OS/2 enthusiasts.  Aside from the (amazing) 
  166.  jugglers that were there, I hung around until late that afternoon for a more 
  167.  intimate demo of the system.  Since there was only one other person watching, 
  168.  I got to ask questions about the system, what the components were like, etc. 
  169.  
  170.  It turns out that the task bar, a la Object Desktop, was "stolen" (almost a 
  171.  direct quote from the IBM gentleman) from the Lotus Smartsuite.  "I hope they 
  172.  didn't pay the billions of dollars for that alone," queried the quantifying 
  173.  Q-ster.  (Heh, Katt doesn't know how easy he has things!) 
  174.  
  175.  The interface, however, was rather stunning and it will likely be the most 
  176.  noticeable improvement over Warp.  No, I haven't forgotten VoiceType, but I 
  177.  don't yet believe that the majority of people are going to use it.  Let's face 
  178.  it - if everyone went for the new and better technology immediately, OS/2 
  179.  would have smashed Windows into the ground a long time ago.  No, people are 
  180.  very inertial, especially when dealing with technology they don't quite yet 
  181.  understand. 
  182.  
  183.  VoiceType 
  184.  
  185.  I don't want to detract from VoiceType, though.  It worked fairly well, 
  186.  although the demoers - is that a word? - did at times have trouble with it. 
  187.  For the record, it was hard-to-tell if the problems were caused by the 
  188.  software or the extreme amount of ambient noise in the large conference 
  189.  center.  I am looking forward to playing with it; hell, if it's good enough, 
  190.  maybe I won't have to type in this column every week.  I still have to get one 
  191.  of those nifty headset microphones before I can use it.  (It figures.  I have 
  192.  over $20,000 of musical equipment sitting next to my computer, but I don't 
  193.  have a headset microphone.) 
  194.  
  195.  TeamConnection 
  196.  
  197.  This is a project management software package which runs on OS/2 using TCP/IP 
  198.  as the network protocol for a truly client/server system allowing multiple 
  199.  people to work on a large project simultaneously.  IBM rattled off a whole 
  200.  list of features to me, but I opted for the evaluation copy of the software. 
  201.  Hopefully, we'll get the real McCoy and Brad will be able to review it in the 
  202.  near future. 
  203.  
  204.  One thing we won't be able to test (I don't think so, at least) but is 
  205.  something you should definately be interested in is distributed building of 
  206.  your product.  You have 30 computers connected via a network - why should only 
  207.  one of them do all of the compiling?  This feature definately sounds fun to 
  208.  watch in action. 
  209.  
  210.  Visual Age 
  211.  
  212.  For those of you who are interested in cross-platform development, IBM's 
  213.  Visual Age product was being demoed on OS/2 and NT with the same user 
  214.  interface (for the most part).  If you've complained about the performance of 
  215.  the Visual Builder (who hasn't?), some help is on the way.  According to the 
  216.  gentlemen I spoke to, IBM segregated the code generator from the builder and 
  217.  (if I remember correctly) rewrote the generator in C.  The visual aspects of 
  218.  the builder are still written in Smalltalk, I infered. 
  219.  
  220.  Where Was Everyone Else? 
  221.  
  222.  Besides IBM and Lotus, there was a small section of IBM's floor space 
  223.  dedicated to ISV's.  DevTech is the only ISV whose name I can remember, 
  224.  though.  This is getting scary, folks.  Where was everyone else? 
  225.  
  226.  I was really disappointed to find (or not find, as the case may be) little 
  227.  OS/2 software outside the confines of the IBM and Lotus sections.  When I say 
  228.  little, I mean little.  There was so little software for OS/2 that I can't 
  229.  even remember seeing any, but something inside tells me that I did indeed see 
  230.  some OS/2 packages. 
  231.  
  232.  This is yet another testimony to the lack of support for OS/2 in the 
  233.  marketplace.  While I don't completely agree with the pronouncement of doom, 
  234.  OS/2 is quickly headed for the ranks of the Amiga OS and Unix, i.e. well 
  235.  known, but not popular among the mainstream users. 
  236.  
  237.  
  238. ΓòÉΓòÉΓòÉ 2. Copyright Notice ΓòÉΓòÉΓòÉ
  239.  
  240. Copyright Notice 
  241.  
  242. EDM/2 is published by IQPac Inc.  IQPac Inc. can be reached via U.S. Mail at 
  243. the following address: 
  244.  
  245. IQPac Inc.
  246. 7 East Broadway, Box 804
  247. New York, NY 10038
  248. U.S.A.
  249.  
  250.  Editor-in-chief     Larry Salomon Jr. (larry_salomon@iqpac.com) 
  251.  Associate editor    Carsten Whimster (carsten_whimster@iqpac.com) 
  252.  Contributing editor Brad Scharf (brad_scharf@iqpac.com) 
  253.  Contributing editor Joe Wyatt (joe_wyatt@iqpac.com) 
  254.  Contributing editor Gordon Zeglinski (gordon_zeglinski@iqpac.com) 
  255.  
  256.  CEO/President       Larry Salomon Jr. (larry_salomon@iqpac.com) 
  257.  
  258.  All material is copyrighted by its original author.  No part of this magazine 
  259.  may be reproduced without permission from the original author. 
  260.  
  261.  This publication may be freely distributed in electronic form provided that 
  262.  all parts are present in their original unmodified form.  A reasonable fee may 
  263.  be charged for the physical act of distribution; no fee may be charged for the 
  264.  publication itself. 
  265.  
  266.  Neither IQPac Inc. nor this publication are affiliated with International 
  267.  Business Machines Corporation. 
  268.  
  269.  OS/2 is a registered trademark of International Business Machines Corporation. 
  270.  Other trademarks are property of their respective owners.  Any mention of a 
  271.  product in this publication does not constitute an endorsement or affiliation 
  272.  unless specifically stated in the text. 
  273.  
  274.  The OS/2 Accredited Logo is a trademark of International Business Machines 
  275.  Corporation and is used by IQPac Inc. under license.  This On-line Publication 
  276.  is independently produced by IQPac Inc. and IBM is not responsible in any way 
  277.  for its contents. 
  278.  
  279.  IQPac Inc. is an accredited member of the IBM Independent Vendor League. 
  280.  
  281.  Copyright Notice - EDM/2 - Jul 1996 - Volume 4, Issue 6 
  282.  
  283.  
  284. ΓòÉΓòÉΓòÉ 3. How Do I Get EDM/2? ΓòÉΓòÉΓòÉ
  285.  
  286. How Do I Get EDM/2? 
  287.  
  288. EDM/2 can be obtained in any of the following ways: 
  289.  
  290. Anonymous FTP on the Internet 
  291.  
  292. hobbes.nmsu.edu in the /os2/newsltr directory. 
  293.  
  294. Elsewhere on the Internet 
  295.  
  296. generalhq.pc.cc.cmu.edu in the /pub/newsletters/edm2 directory. 
  297.  
  298. The EDM/2 mailing list.  Send an empty message to edm2-info@knex.mind.org to 
  299. receive a file containing (among other things) instructions for subscribing to 
  300. EDM/2. 
  301.  
  302. On Compuserve 
  303.  
  304. All back issues are available in the forum OS2DF2, section 15. 
  305.  
  306. On BBS's 
  307.  
  308. From BBS's in Denmark, send email to Jesper Nielsen at jesniels@internet.dk for 
  309. a location near you. 
  310.  
  311. How do I Get EDM/2? - EDM/2 - Jul 1996 - Volume 4, Issue 6 
  312.  
  313.  
  314. ΓòÉΓòÉΓòÉ 4. Watermarking Your Printouts ΓòÉΓòÉΓòÉ
  315.  
  316.  
  317. ΓòÉΓòÉΓòÉ 4.1. Watermarking Your Printouts ΓòÉΓòÉΓòÉ
  318.  
  319.  Watermarking Your Printouts 
  320.  
  321. Written by Larry Salomon, Jr. 
  322.  
  323. Introduction 
  324.  
  325. In the "how did they do that" category, watermarking is a concept that looks 
  326. easy but, for those with little graphics experience (like me), is more 
  327. difficult than apparent at first glance.  For those who are not familiar with 
  328. the term "watermark," it is a textual element that has the following 
  329. properties: 
  330.  
  331.      It is drawn behind all other elements on a printed page. 
  332.      It is unobtrusive so that it does detract from the reader's ability to 
  333.       easily read what else is on the page 
  334.      It is rotated at some arbitrary angle, usually spanning the page from the 
  335.       lower left corner to the upper right corner 
  336.  
  337.  See figure 1 for an example of a watermark. 
  338.  
  339.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  340.  
  341.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  342.  
  343.  Figure 1)  Sample watermark 
  344.  
  345.  Watermarking is usually performed to indicate a security level of a document 
  346.  ("Confidential") or to indicate that the printout comes from a demo or 
  347.  unregistered version of an application.  There are, however, many other 
  348.  possible uses which you will discover. 
  349.  
  350.  This article will discuss how watermarking can be done in OS/2 and will 
  351.  briefly cover topics such as color use, fonts, graphics boundary 
  352.  determination, and rotational transformations. 
  353.  
  354.  Watermarking Your Printouts - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  355.  
  356.  
  357. ΓòÉΓòÉΓòÉ 4.2. How Would You Do It? ΓòÉΓòÉΓòÉ
  358.  
  359.  How Would You Do It? 
  360.  
  361. Before we begin coding, we should consider a high-level design so that we know 
  362. in what direction we are travelling; this will serve as our flowchart for the 
  363. function which will do the watermarking. 
  364.  
  365. Our first decision will be to determine what the interface is.  This allows us 
  366. to consider in advance the flexibility that we will offer the application 
  367. developer using this function and design with this flexibility in mind.  Since 
  368. watermarking can be used in a variety of situations, the text to be used should 
  369. be specified by the caller.  The angle of rotation should also be specified by 
  370. the caller to give more control over the look of the watermark. Finally, we 
  371. need the handle of the presentation space to be used.  We have, therefore, the 
  372. following prototype: 
  373.  
  374. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  375.  
  376.  
  377. BOOL doWatermark(HPS hpsPrn,PCHAR pchText,USHORT usAngle);
  378.  
  379. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  380.  
  381. As a corollary exercise to designing the prototype, let us consider any 
  382. limitations and/or restrictions that we will impose. 
  383.  
  384.      As we will see, rotations can only be done on a "normal" presentation 
  385.       space, so the HPS must have been created with the GPIT_NORMAL flag in the 
  386.       call to GpiCreatePS(). 
  387.      The presentation space must be associated with a printer device. 
  388.      The printer driver and/or device must support color or dithering (i.e. 
  389.       no monochrome printers) 
  390.      If we were to rotate the text more than 90 degrees, it wouldn't be easily 
  391.       readable, so the angle should be in the range 0-90 inclusive. 
  392.  
  393.  Now we may proceed to determining the procedure for drawing the watermark. 
  394.  
  395.  Consider the following problem:  we want the text to be as large as possible 
  396.  (without having it clipped on the printed page) but we cannot determine, at 
  397.  compile time, the size of each character.  How do we calculate this at run 
  398.  time? 
  399.  
  400.  The solution is easy to describe:  we set the size of the character box to 
  401.  some value that we know to be too big and then draw the text; if the text is 
  402.  too big, we reduce the size of the character box by some amount and repeat. 
  403.  When the text completely fits within the printed page, we stop looping. 
  404.  
  405.  Sounds easy, huh?  Since this is the only "difficult" part of the design, we 
  406.  can now describe the procedure as such: 
  407.  
  408.    1. Indicate a rotation of the number of degrees specified. 
  409.    2. Set the font to something "nice." 
  410.    3. Set the character size to be very large. 
  411.    4. Draw the text. 
  412.    5. If the text is too big, reduce the character size by some amount and goto 
  413.       step 4. 
  414.    6. Set the text color to be very light. 
  415.    7. Draw the text using the calculated character size. 
  416.    8. Restore the font to the one originally in use. 
  417.  
  418.  This procedure will work, as we will see.  For those of you sharp enough to 
  419.  catch the caveat that drawing the text in the determination part will 
  420.  obliterate the printout, keep reading. 
  421.  
  422.  Watermarking Your Printouts - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  423.  
  424.  
  425. ΓòÉΓòÉΓòÉ 4.3. Colors ΓòÉΓòÉΓòÉ
  426.  
  427.  Colors 
  428.  
  429. Although the Gpi subsystem added the concept of a color palette, I have never 
  430. investigated whether or not palettes will work with hardcopy devices. To save 
  431. myself the aggrevation, I decided to stick with logical color tables in RGB 
  432. mode, which amounts to the same thing.  Logical color tables are a dated 
  433. concept that worked well when the majority of displays were EGA or VGA and 
  434. dithering had to be used to simulate the colors that we really wanted. Now that 
  435. SVGA is considered standard equipment, logical color tables are considered 
  436. obsolete.  In other words, I probably doomed myself by using them. They work 
  437. for the moment, however, so I'll use them anyway. 
  438.  
  439. A logical color table is a table of colors which is requested by the 
  440. application for use within a presentation space.  Gpi maps these "logical" 
  441. colors to the "physical" colors defined by the hardware palette.  For those 
  442. colors that cannot by described adequately, Gpi uses dithering (alternating two 
  443. or three colors in a 2x2 or 3x3 matrix) to simulate the color requested. These 
  444. are normally used when the default RGB values for the CLR_ constants are not 
  445. good enough and also when you want to specify the RGB value directly in the Gpi 
  446. calls.  We need the latter capability, so let's tell the Gpi subsystem this: 
  447.  
  448. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  449.  
  450.  
  451. #define DW_TEXT_COLOR            0x00CCCCCC
  452.  
  453. else if (!GpiCreateLogColorTable(hpsPrn,0,LCOLF_RGB,0,0,NULL))
  454.    ;
  455.  
  456. else if (!GpiSetColor(hpsPrn,DW_TEXT_COLOR))
  457.    ;
  458.  
  459. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  460.  
  461. Figure 2)  Switching to RGB mode. 
  462.  
  463. GpiCreateLogColorTable() takes the following parameters: 
  464.  
  465. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  466.  
  467.  
  468. BOOL GpiCreateLogColorTable(HPS hpsHps,
  469.                             ULONG ulFlags,
  470.                             LONG lMode,
  471.                             LONG lStart,
  472.                             LONG lCount,
  473.                             PLONG plTable);
  474.  
  475. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  476.  
  477. hpsHps specifies the presentation space.  ulFlags specifies zero or more LCOL_ 
  478. flags and is unused by us.  lMode specifies the mode of the color table and 
  479. affects how the remaining parameters are interpreted and may be one of the 
  480. following: 
  481.  
  482.      LCOLF_DEFAULT - returns the color table to the default mode, which is 
  483.       indexed.  This uses the CLR_ constants that we all know and love. 
  484.      LCOLF_INDRGB - indicates that plTable should be interpreted as an array 
  485.       of pairs of LONG values, where the first LONG is the index into the color 
  486.       table where the second LONG (which is an RGB value) is to be placed. 
  487.      LCOLF_CONSECRGB - indicates that plTable specifies an array of LONG 
  488.       values (which is lCount large and contains RGB values) which replace the 
  489.       corresponding entries in the color table beginning at lStart. 
  490.      LCOLF_RGB - indicates that lStart, lCount, and plTable are to be ignored 
  491.       and that RGB values will be used in any Gpi call that requires a color. 
  492.  
  493.  Note how we specify a very light gray for the color (0xCC is used for the red, 
  494.  green, and blue components of the color).  The results in almost transparent 
  495.  text. 
  496.  
  497.  Watermarking Your Printouts - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  498.  
  499.  
  500. ΓòÉΓòÉΓòÉ 4.4. Fonts ΓòÉΓòÉΓòÉ
  501.  
  502.  Fonts 
  503.  
  504. In his book, Charles Petzold described a nice, generic way to enumerate the 
  505. fonts on a system and set the current font to be one of your own choosing. 
  506. While this is great for the general case and gleefully covers the situation 
  507. when a font is not installed on a system, it is my opinion that, if you need 
  508. one of the ATM fonts shipped with the system, this is too much work.  Given the 
  509. awe that high-quality graphics generate and the ever-shrinking cost of disk 
  510. space, it is my claim that few people (if any) will choose not to install all 
  511. of the fonts that OS/2 includes.  With this in mind, I now present the "poor 
  512. man's method of selecting an ATM font:"  initialize a FATTRS structure with 
  513. zeros (except for three fields), call GpiCreateLogFont(), and then call 
  514. GpiSetCharSet(). 
  515.  
  516. Done.  See how easy that was?  Let's look at the details: 
  517.  
  518. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  519.  
  520.  
  521. faFont.usRecordLength=sizeof(faFont);
  522. faFont.fsSelection=0;
  523. faFont.lMatch=0;
  524. strcpy(faFont.szFacename,"Helvetica");
  525. faFont.idRegistry=0;
  526. faFont.usCodePage=GpiQueryCp(hpsPrn);
  527. faFont.lMaxBaselineExt=0;
  528. faFont.lAveCharWidth=0;
  529. faFont.fsType=0;
  530. faFont.fsFontUse=FATTR_FONTUSE_OUTLINE | FATTR_FONTUSE_TRANSFORMABLE;
  531.  
  532. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  533.  
  534. Figure 3)  Initializing the FATTRS structure. 
  535.  
  536. As you can see, the only three fields that we initialize are the font name 
  537. (FATTRS.szFacename), the codepage (FATTRS.usCodePage), and the flags describing 
  538. what type of font we want (FATTRS.usFontUse).  As you can also see above, 
  539. initializing these fields is trivial.  The flags FONTUSE_TRANSFORMABLE and 
  540. FONTUSE_OUTLINE indicate that we want a font that is "transformable" (i.e. 
  541. rotatable and resizable) and is an ATM font, respectively. 
  542.  
  543. Shown below is the code to actually acquire the font for use. 
  544.  
  545. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  546.  
  547.  
  548. #define DW_FONT_HELV             1
  549.  
  550. //----------------------------------------------------------------------
  551. // Create the logical font.
  552. //----------------------------------------------------------------------
  553. else if (GpiCreateLogFont(hpsPrn,NULL,DW_FONT_HELV,&faFont)==GPI_ERROR)
  554.    ;
  555.  
  556. //----------------------------------------------------------------------
  557. // Set the font into the HPS.
  558. //----------------------------------------------------------------------
  559. else if (!GpiSetCharSet(hpsPrn,DW_FONT_HELV))
  560.    ;
  561.  
  562. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  563.  
  564. Figure 4) Creating the logical font and setting it is the current font. 
  565.  
  566. GpiCreateLogFont() creates an association between the HPS and the physical 
  567. font.  It takes the following parameters: 
  568.  
  569. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  570.  
  571.  
  572. LONG GpiCreateLogFont(HPS hpsHps,
  573.                       PSTR8 psName,
  574.                       LONG lFontId,
  575.                       PFATTRS pfaAttrs);
  576.  
  577. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  578.  
  579. hpsHps specifies the presentation space in which a logical font which 
  580. represents the physical font will be created.  psName is used for creating 
  581. SAA-conforming metafiles and is not used normally (specify NULL for this). 
  582. lFontId is the identifier by which the font will be known and must be unique 
  583. for this HPS.  pfaAttrs points to the FATTRS structure which describes the font 
  584. we want.  It returns FONT_MATCH if the font was found, FONT_DEFAULT if the font 
  585. was not found but a substitute font was, or GPI_ERROR if an error occurred. 
  586.  
  587. GpiSetCharSet() specifies the current font to be used and takes the following 
  588. parameters. 
  589.  
  590. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  591.  
  592.  
  593. BOOL GpiSetCharSet(HPS hpsHps,LONG lFontId);
  594.  
  595. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  596.  
  597. hpsHps specifies the presentation space.  lFontId is the identifier of the font 
  598. used in the GpiCreateLogFont() call. 
  599.  
  600. Now that we have the font we want, we have to know how to specify the size that 
  601. we want.  This only pertains to transformable fonts, which is why we specified 
  602. FONTUSE_TRANSFORMABLE in the FATTRS structure. 
  603.  
  604. Fixed Decimal Arithmetic 
  605.  
  606. When the Gpi subsystem was developed, floating point processors were not part 
  607. of the CPU, nor were they present as separate chips in the majority of 
  608. computers used at that time.  So, to avoid the penalty of emulating floating 
  609. point operations in software, the Gpi developers decided to use fixed point 
  610. arithmetic when non-integral numbers were needed.  For those of you unfamiliar 
  611. with the concept, fixed point arithmetic implies a decimal point, even though 
  612. one is not actually specified in the number. 
  613.  
  614. The Gpi subsystem adds a twist to this, however.  Instead of using base-10, it 
  615. uses base-10 only for the integer part of the number and base-64K for the 
  616. fractional part.  In other words, if you have fixed point number i.f, you 
  617. convert this to a floating point number using the formula i+f/64K.  This 
  618. denominator was not chosen to be sadistic.  You will remember that 64K-1 is the 
  619. maximum value expressable in 16- bits, which allows us to imply the denominator 
  620. and yet get a complete range of fractional values.  If you restrict the integer 
  621. portion to 16-bits also, the total number fits nicely in a ULONG. 
  622.  
  623. Why is all of this relevant?  Because character sizes are specified using 
  624. fixed-point numbers, of course.  Let me now introduce the SIZEF structure which 
  625. is similar to the SIZEL structure except that the cx and cy fields are of type 
  626. FIXED instead of LONG.  Yes, yes, they amount to the same thing, but it's the 
  627. principle that matters.  The only other piece of information that you need to 
  628. know is that fonts are designed such that they display with no distortion if 
  629. and only if the horizontal component of the character size is equal to the 
  630. vertical component.  (The box that has the dimensions of the character size is 
  631. known as the "character box.") 
  632.  
  633. The code to set the character box (initially) is shown below.  Note the 
  634. (necessary) call to GpiSetCharMode() which tells Gpi that we want to rotate 
  635. text in the presentation space. 
  636.  
  637. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  638.  
  639.  
  640. //----------------------------------------------------------------------
  641. // Get the HPS dimensions.  GpiQueryPS() does not have an error return
  642. // code defined.
  643. //----------------------------------------------------------------------
  644. GpiQueryPS(hpsPrn,&szlHps);
  645.  
  646. szfChar.cx=MAKEFIXED(szlHps.cy/2,0);
  647. szfChar.cy=szfChar.cx;
  648.  
  649.   :
  650.   :
  651.  
  652. //----------------------------------------------------------------------
  653. // Set the character mode to 3 so that we can rotate them.
  654. //----------------------------------------------------------------------
  655. else if (!GpiSetCharMode(hpsPrn,CM_MODE3))
  656.    ;
  657.  
  658. else if (!GpiSetCharBox(hpsPrn,&szfChar))
  659.    ;
  660.  
  661. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  662.  
  663. Figure 5)  Setting the character box to its initial value. 
  664.  
  665. Again, see how easy this is?  And you thought fonts were difficult! 
  666.  
  667. Watermarking Your Printouts - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  668.  
  669.  
  670. ΓòÉΓòÉΓòÉ 4.5. Transformations ΓòÉΓòÉΓòÉ
  671.  
  672.  Transformations 
  673.  
  674. One class that I had to take as a Computer Science major which was both 
  675. interesting and boring at the same time was Linear Algebra.  In this class we 
  676. learned everything about matrices we ever wanted to know and even some stuff 
  677. that we never wanted to know.  (How many of you actually used your knowledge of 
  678. Eigen vectors after graduating?)  One interesting application of matrices is 
  679. transformations.  In a nutshell, by properly initializing a matrix of the 
  680. appropriate size, one can scale, rotate, shear, or even map a point in 3-D 
  681. space to 2-D space. 
  682.  
  683. The Gpi subsystem provides two ways of doing transformations, just as it does 
  684. fonts:  the hard way and the easy way.  Because we'll never finish this article 
  685. if we describe the hard way, we'll use the easy way.  As with fonts, the easy 
  686. way doesn't provide the same flexibility as the hard way, but we don't need to 
  687. perform all sorts of fancy transformations either.  Just a simple rotation 
  688. would be sufficient. 
  689.  
  690. Fortunately, the easy way also includes a function to do this for us: 
  691. GpiRotate().  It applies a rotation of an arbitrary angle to an entity called 
  692. (as you would imagine) a transformation matrix. 
  693.  
  694. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  695.  
  696.  
  697. BOOL GpiRotate(HPS hpsHps,
  698.                PMATRIXLF pmlMatrix,
  699.                LONG lFlags,
  700.                FIXED fAngle,
  701.                PPOINTL pptlOrigin);
  702.  
  703. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  704.  
  705. hpsHps specifies the presentation space.  pmlMatrix points to the 
  706. transformation matrix, which we will not describe here.  lFlags specifies how 
  707. the rotation is to be performed.  fAngle specifies the angle of rotation in 
  708. degrees.  pptlOrigin specifies the point around which the rotation is to be 
  709. performed. 
  710.  
  711. lFlags can be one of the following values: 
  712.  
  713.      TRANSFORM_REPLACE - specifies that the result is to replace the 
  714.       transformation already specifed in pmlMatrix. 
  715.      TRANSFORM_ADD - specifies that the rotation is to be applied after the 
  716.       transformation specified in pmlMatrix. 
  717.      TRANSFORM_PREEMPT - specifies that the rotation is to be applied before 
  718.       the transformation specified in pmlMatrix. 
  719.  
  720.  The resulting transformation matrix is returned in pmlMatrix regardless of the 
  721.  option specified. 
  722.  
  723.  What does this do for us?  When the resulting transformation matrix is applied 
  724.  to the HPS, it allows us to draw using a coordinate system oriented in the 
  725.  usual fashion (i.e.  the x axis is horizontal and increases to the right and 
  726.  the y axis is vertical and increases upward).  The output, however, is rotated 
  727.  by the angle specified. 
  728.  
  729.  The Gpi subsystem provides many layers of transformation, and we will not 
  730.  describe them here because they are too advanced for the scope of this article 
  731.  (read:  I don't understand them myself).  Suffice it to say that the function 
  732.  we need to effect the transformation represented by pmlMatrix is 
  733.  GpiSetModelTransformMatrix().  It takes the following parameters: 
  734.  
  735.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  736.  
  737.  
  738.   BOOL GpiSetModelTransformMatrix(HPS hpsHps,
  739.                                   LONG lInitFields,
  740.                                   PMATRIXLF pmlMatrix,
  741.                                   LONG lFlags);
  742.  
  743.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  744.  
  745.  hpsHps specifies the presentation space.  lInitFields is the number of fields 
  746.  in pmlMatrix that are initialized and, for us, will always be 9 (meaning that 
  747.  a transformation matrix has size 3x3).  pmlMatrix specifies the transform to 
  748.  be applied.  lFlags specifies how the transformation is to be applied and can 
  749.  have the same value as the equivalent parameter in GpiRotate(). 
  750.  
  751.  The code to set the rotation is shown below: 
  752.  
  753.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  754.  
  755.  
  756.   //----------------------------------------------------------------------
  757.   // Rotate about the center of the page.
  758.   //----------------------------------------------------------------------
  759.   else if (!GpiRotate(hpsPrn,
  760.                       &mxRotate,
  761.                       TRANSFORM_REPLACE,
  762.                       MAKEFIXED(usAngle,0),
  763.                       &ptlPoint))
  764.      ;
  765.  
  766.   else if (!GpiSetModelTransformMatrix(hpsPrn,
  767.                                        9,
  768.                                        &mxRotate,
  769.                                        TRANSFORM_REPLACE))
  770.      ;
  771.  
  772.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  773.  
  774.  Figure 6)  Setting up the rotation. 
  775.  
  776.  Watermarking Your Printouts - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  777.  
  778.  
  779. ΓòÉΓòÉΓòÉ 4.6. Graphics Boundaries ΓòÉΓòÉΓòÉ
  780.  
  781.  Graphics Boundaries 
  782.  
  783. The title of this section implies that it is possible to determine the 
  784. boundaries of any given set of graphics commands.  Since it would be useless 
  785. otherwise, it makes sense to assume that it is also possible to do so without 
  786. affecting the current output in the HPS. 
  787.  
  788. There is a little known, but powerful, Gpi function which performs both of 
  789. these actions:  GpiSetDrawControl().  It, in a general sense, controls whether 
  790. or not specific functionality in the Gpi is in effect.  (Yes, this is 
  791. confusing.  Keep reading and it should make sense.)  It takes the following 
  792. parameters: 
  793.  
  794. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  795.  
  796.  
  797. BOOL GpiSetDrawControl(HPS hpsHps,LONG lControl,LONG lValue);
  798.  
  799. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  800.  
  801. hpsHps specifies the presentation space.  lControl specifies a DCTL_ constant 
  802. indicating which attribute of the Gpi subsystem you which to change. lValue 
  803. specifies DCTL_ON or DCTL_OFF to turn the attribute on or off, respectively. 
  804.  
  805. The two values of lControl that we're interested in are DCTL_DISPLAY and 
  806. DCTL_BOUNDARY: 
  807.  
  808. DCTL_DISPLAY specifies whether or not anything is to be drawn on the output 
  809. device.  With the exception of GpiErase() any drawing function results in a NOP 
  810. if DCTL_OFF is specified. 
  811.  
  812. DCTL_BOUNDARY specifies if the Gpi subsystem should keep track of the extents 
  813. of the units (pels, low English, etc.)  that were affected by a drawing 
  814. command.  This information can be retrieved using GpiQueryBoundaryData().  It 
  815. is not affected by the state of the DCTL_DISPLAY attribute. 
  816.  
  817. You should already be able to see how we are going to use this function. 
  818.  
  819. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  820.  
  821.  
  822. //----------------------------------------------------------------------
  823. // Turn off drawing and turn on boundary collection
  824. //----------------------------------------------------------------------
  825. else if (!GpiSetDrawControl(hpsPrn,DCTL_DISPLAY,DCTL_OFF))
  826.    ;
  827.  
  828. else if (!GpiSetDrawControl(hpsPrn,DCTL_BOUNDARY,DCTL_ON))
  829.    ;
  830.  
  831.   :
  832.   :
  833.  
  834. //-------------------------------------------------------------------
  835. // Turn on drawing and turn off boundary collection
  836. //-------------------------------------------------------------------
  837. else if (!GpiSetDrawControl(hpsPrn,DCTL_DISPLAY,DCTL_ON))
  838.    ;
  839.  
  840. else if (!GpiSetDrawControl(hpsPrn,DCTL_BOUNDARY,DCTL_OFF))
  841.    ;
  842.  
  843. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  844.  
  845. Figure 7) Setting the drawing and boundary data collection attributes. 
  846.  
  847. The code above allows us to, inside the bracket, determine the character box 
  848. size for the watermark. 
  849.  
  850. This stuff is so easy, you should be writing this article instead of me. 
  851.  
  852. Watermarking Your Printouts - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  853.  
  854.  
  855. ΓòÉΓòÉΓòÉ 4.7. The Result ΓòÉΓòÉΓòÉ
  856.  
  857.  The Result 
  858.  
  859. We now have enough knowledge to successfully implement the design that we 
  860. deduced earlier.  The function as well as the application which calls the 
  861. function are in the sample source code that accompanies this article. Although 
  862. you should be able to understand the code competely, any questions or comments 
  863. are welcome via email; my address is larry_salomon@iqpac.com . Enjoy! 
  864.  
  865. Watermarking Your Printouts - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  866.  
  867.  
  868. ΓòÉΓòÉΓòÉ 5. A Progress-indicating Status Line in C++ (Part 2) ΓòÉΓòÉΓòÉ
  869.  
  870.  
  871. ΓòÉΓòÉΓòÉ 5.1. A Progress-indicating Status Line in C++ (Part 2) ΓòÉΓòÉΓòÉ
  872.  
  873.  A Progress-indicating Status Line in C++ (Part 2) 
  874.  
  875. Written by Stefan Ruck 
  876.  
  877. Introduction 
  878.  
  879. In the first part of this small series, published in EDM/2 Volume 4, Issue 5, I 
  880. introduced the progress-indicating status line and the needed message handler 
  881. to you.  This time I will show you a simple base file class which is wrapped 
  882. around the API-calls and a derived class which sends status messages to a given 
  883. status line. 
  884.  
  885. A Progress-indicating Status Line in C++ (Part 2) - EDM/2 - Jul 1996 - Volume 4 
  886. Issue 6 
  887.  
  888.  
  889. ΓòÉΓòÉΓòÉ 5.2. The Base File Class ΓòÉΓòÉΓòÉ
  890.  
  891.  The Base File Class 
  892.  
  893. The primary purpose of this class named AFile is to hide the main file-handling 
  894. API functions.  It just covers opening, reading, writing and of course closing 
  895. a file.  Let's have a look at its member. 
  896.  
  897. The class AFile is defined in afile.hpp and afile.cpp 
  898.  
  899. The Constructor Member 
  900.  
  901. There is only one constructor which takes two arguments, pBuffer (a PVOID) and 
  902. ulBufferSize (a ULONG).  They are initialized to zero by default. 
  903.  
  904. What are these arguments good for?  If you know the buffer you want to read the 
  905. file's contents into, and it's size, you can pass a pointer to the buffer and 
  906. the buffer's size to the file object as soon as you create it.  When you do any 
  907. operation (reading, writing) later on this file you don't have to pass the 
  908. buffer and its size anymore because they are already known.  This may be 
  909. useful, e.g.  for configuration files. 
  910.  
  911. The members which store this information are declared as const so they can't be 
  912. changed after construction. 
  913.  
  914. The open Members 
  915.  
  916. The difference between the two AFile::open members is the way you pass the 
  917. filename.  It can be a pointer to a string or a reference to an IString object. 
  918. The other arguments are similar to the DosOpen function.  The only difference 
  919. is that the file handle is not needed because it's a private member of the file 
  920. object. 
  921.  
  922. The AFile::reOpen member can only be used when a file object was opened before 
  923. and is actually closed.  Because the filename of a AFile object is kept in a 
  924. private member you don't have to pass it again when you re-open the same file 
  925. using the same object. 
  926.  
  927. The Close Member 
  928.  
  929. This member is implemented for closing the file during the lifetime of the file 
  930. object.  Destroying a file object always closes the file. 
  931.  
  932. The read and write Members 
  933.  
  934. The default value of both parameters (PVOID pBuffer and ULONG ulBufferSize) is 
  935. 0L.  If you call AFile::read or AFile::write without passing a pointer to the 
  936. buffer and/or the buffer's size the values passed to the constructor are given 
  937. to the DOS-API-functions. 
  938.  
  939. In addition to the OS/2 API return-values there are three more return-values: 
  940.  
  941.      AFILE_FILE_NOT_OPEN is returned in case the file connected to the object 
  942.       is not open. 
  943.      AFILE_NO_BUFFER_POINTER indicates that no pointer to a buffer is passed 
  944.       to the constructor or to the member.  And AFILE_NO_BUFFER_SIZE means that 
  945.       the size of the buffer is missing. 
  946.  
  947.  The Refresh-Flag on AFile::getFileSize 
  948.  
  949.  This flag is used internally when the AFile::queryFileInfo member is called. 
  950.  If it is set to true DosQueryFileInfo is called even if nothing about the file 
  951.  has changed.  If it is set to false DosQueryFileInfo is only called when it 
  952.  was not called before (AFile::m_pFilestatus3, which keeps the file info, is 
  953.  not set in this case).  You have to handle it yourself when the refresh-flag 
  954.  should be set. 
  955.  
  956.  A Progress-indicating Status Line in C++ (Part 2) - EDM/2 - Jul 1996 - Volume 
  957.  4 Issue 6 
  958.  
  959.  
  960. ΓòÉΓòÉΓòÉ 5.3. The Message-Sending File Class ΓòÉΓòÉΓòÉ
  961.  
  962.  The Message-Sending File Class 
  963.  
  964. The main purpose of this article is to present a class which uses the 
  965. progress-indicating status line to show the state of a process.  This class is 
  966. AEditFile.  It is defined in editfile.hpp and editfile.cpp. 
  967.  
  968. We can't use AFile directly because the methods AFile::read and AFile::write do 
  969. not return until they have finished and the whole file is read / written.  So 
  970. what we need now are methods which read/write the data not in one big step but 
  971. in a few small ones.  They are AFileEdit::read and AFileEdit::write. 
  972.  
  973. The class AFile is the base class of AEditFile, which posts MYM_STATUS_PROCEED 
  974. messages (I hope you remember this message) to the status line while 
  975. reading/writing a file.  The differences between this class and AFile are the 
  976. members for reading/writing, and the fact that this class keeps the file's 
  977. contents itself.  So you can't pass a pointer to the buffer or the buffer's 
  978. size to the constructor. 
  979.  
  980. The size of the file can't be changed. 
  981.  
  982. This class doesn't work on files of no size. 
  983.  
  984. I think there is no explanation needed for the constructor and destructor. 
  985.  
  986. The read Member 
  987.  
  988. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  989.  
  990.  
  991. //**************************************************************************
  992. // AEditFile :: read - read the data into the buffer                       *
  993. //**************************************************************************
  994. APIRET AEditFile :: read (HWND hwndStatusLine)
  995. {
  996.   ULONG ulBytesLeftToRead = m_ulFileSize;                          // set the variables
  997.   ULONG ulReadAtBufferPos = 0;
  998.   APIRET ret;
  999.  
  1000.   if(!m_pFileContents)                                             // no buffer allocated?
  1001.      throw m_pFileContents;                                        // throw an exception
  1002.  
  1003.   m_bStopProcess = false;                                          // do not stop the process
  1004.  
  1005.   while(ulBytesLeftToRead)                                         // as long as there are still some bytes left to read
  1006.         {
  1007.          ret = AFile :: read (m_pFileContents + ulReadAtBufferPos, // read a block of data
  1008.                               (ulBytesLeftToRead > (ULONG) eBytesToRead ? eBytesToRead : ulBytesLeftToRead));
  1009.          if(ret && ret != ERROR_MORE_DATA)                         // a serious error occured?
  1010.             break;                                                 // yes, break the loop
  1011.          if(m_bStopProcess)                                        // stop the process?
  1012.             {                                                      // yes
  1013.              m_bStopProcess = false;                               // reset the flag
  1014.              return (ERROR_MORE_DATA);                             // return
  1015.             }
  1016.          if(hwndStatusLine)                                        // is a handle of a status line passed?
  1017.             WinPostMsg (hwndStatusLine, MYM_STATUS_PROCEED, 0, 0); // yes, post the message
  1018.          ulBytesLeftToRead -= getBytesRead ();                     // decrease the number of bytes left to read
  1019.          ulReadAtBufferPos += getBytesRead ();                     // increase the position where to place the data
  1020.         }
  1021.  
  1022.   return (ret);
  1023. }
  1024.  
  1025. Figure 1) AEditFile::read 
  1026.  
  1027. AEditFile holds its own buffer (see "The allocateDataBuffer Member" later in 
  1028. this article).  So there's no pointer to a buffer or the buffer size needed as 
  1029. a parameter.  But this member needs the HWND of the status line which indicates 
  1030. the progress. 
  1031.  
  1032. Because we read the data in (maybe) several steps, we must compute the number 
  1033. of bytes left to read (stored in ulBytesLeftToRead).  And we have to keep the 
  1034. position to append the new data block in the buffer.  This value is kept by 
  1035. ulReadAtBufferPos. 
  1036.  
  1037. If the buffer was not allocated by AEditFile::allocateDataBuffer, an exception 
  1038. of type char * is thrown. 
  1039.  
  1040. As you might remember we want to use this member to read a file inside of a 
  1041. multi-threaded environment.  Setting the m_bStopProcess to true using 
  1042. AEditFile::stopProcess, the main thread is able to terminate the operation 
  1043. without terminating the sub thread e.g.  by calling IThread::stop (which should 
  1044. only be used in cases of "abnormal termination".  For further information refer 
  1045. to Leong, Law, Love, Tsuji, Olson, "OS/2 C++ Class Library, Power GUI 
  1046. Programming with C Set++", New York, 1993, John Wiley & Sons, p. 533f). 
  1047. AEditFile::stopProcess is useful e.g.  if the user closes the program or wants 
  1048. to abort the process by pressing ESC.  If the process is stopped by setting 
  1049. AEditFile::m_bStopProcess to true, AEditFile::read returns ERROR_MORE_DATA. 
  1050.  
  1051. AEditFile::read uses AFile::read to read the data.  But it calls AFile::read 
  1052. several times, depending on the file's size.  Every time AFile::read is called, 
  1053. a block of AEditFile::bytesToRead or ulBytesLeftToRead bytes, depending on the 
  1054. amount of bytes left to read, is read.  As soon as a file is larger than 
  1055. AEditFile::bytesToRead, it will be read in several steps. Every time a block is 
  1056. read, a MYM_STATUS_PROCEED message is posted to the status line. 
  1057.  
  1058. This line of code may seem a little bit cryptic to some of you:  ret = AFile :: 
  1059. read (m_pFileContents + ulReadAt BufferPos, (ulBytesLeftToRead > (ULONG) 
  1060. eBytesToRead ?  eBytesToRead :  ulBytesLeftToRead));.  Well, I use the ? 
  1061. operator to check if the block of data left to read (ulBytesLeftToRead) is 
  1062. larger than the block I want to read by default (AEditFile::eBytesToRead).  If 
  1063. so, AEditFile::eBytesToRead bytes is passed to AFile::read, oth erwise 
  1064. ulBytesLeftToRead is passed. 
  1065.  
  1066. Because we may not read the whole file in at once, AFile::read may return 
  1067. ERROR_MORE_DATA.  This is correct, so I accept this return value.  Any other 
  1068. non-zero return-value will break the read loop. 
  1069.  
  1070. Only if a handle to a status line window is passed will the MYM_STATUS_PROCEED 
  1071. message be posted. 
  1072.  
  1073. Every time a block of data is read, the position to place the data inside of 
  1074. the buffer (ulReadAtBufferPos) is increased by bytes read (returned by 
  1075. AFile::getBytesRead) while the ulBytesLeftToRead is decreased by the same 
  1076. value. 
  1077.  
  1078. The write Member 
  1079.  
  1080. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1081.  
  1082.  
  1083. //**************************************************************************
  1084. // AEditFile :: write - write the data from the buffer                     *
  1085. //**************************************************************************
  1086. APIRET AEditFile :: write (HWND hwndStatusLine)
  1087. {
  1088.   ULONG ulBytesLeftToWrite = m_ulFileSize;    // set the variables
  1089.   ULONG ulWriteFromBufferPos = 0;
  1090.   APIRET ret;
  1091.  
  1092.   if(!m_pFileContents)                                             // no buffer allocated?
  1093.      throw m_pFileContents;                                        // throw an exception
  1094.  
  1095.   m_bStopProcess = false;                                          // do not stop the process
  1096.  
  1097.   while(ulBytesLeftToWrite)                                        // as long as there are still some bytes left to write
  1098.         {
  1099.          if((ret = AFile :: write (m_pFileContents + ulWriteFromBufferPos, // write a block of data
  1100.                                    (ulBytesLeftToWrite > (ULONG) eBytesToRead ? eBytesToRead : ulBytesLeftToWrite))))
  1101.             break;                                                 // if not 0 == NO_ERROR returned, break the loop
  1102.          if(m_bStopProcess)                                        // stop the process?
  1103.             {                                                      // yes
  1104.              m_bStopProcess = false;                               // reset the flag
  1105.              return (ERROR_MORE_DATA);                             // return
  1106.             }
  1107.          if(hwndStatusLine && ulBytesLeftToWrite)                  // is a handle of a status line passed?
  1108.             WinPostMsg (hwndStatusLine, MYM_STATUS_PROCEED, 0, 0); // yes, post the message
  1109.          ulBytesLeftToWrite -= getBytesWritten ();                 // decrease the number of bytes left to write
  1110.          ulWriteFromBufferPos += getBytesWritten ();               // increase the (buffer-)position from where to write the data
  1111.        }
  1112.  
  1113.   return (ret);
  1114. }
  1115.  
  1116. Figure 2) AEditFile::write 
  1117.  
  1118. This member is similar to AEditFile::read, so I think there is just a little 
  1119. bit of explanation needed. 
  1120.  
  1121. The proceed message is only posted if there are bytes left to write. Otherwise 
  1122. the status line will display a per centage greater than 100. 
  1123.  
  1124. AEditFile::write writes the data, like DosWrite does, at the current position 
  1125. of the file pointer set by former read or write operations.  To set the 
  1126. file-pointer, you have to use DosSetFilePtr or better create a 
  1127. AFile::setFilePtr member and use this one.  I did not include such a member to 
  1128. AFile because I never keep a file open while editing it.  And on every file 
  1129. open the file-pointer is set to the beginning of the file. 
  1130.  
  1131. The allocateDataBuffer Member 
  1132.  
  1133. This member is used to allocate the memory which keeps the file's contents. You 
  1134. should not call it before the file itself is open because the file size is 
  1135. needed. 
  1136.  
  1137. If the memory is allocated successfully or a block of memory is already 
  1138. allocated, it returns true.  If the file is not open, it returns false.  It 
  1139. throws an exception of type ULONG if the size of the file is 0 or the size can 
  1140. not be retrieved.  An exception of type char * is thrown if the memory 
  1141. allocation itself fails.  So this member should be used always inside a 
  1142. try/catch block. 
  1143.  
  1144. A Progress-indicating Status Line in C++ (Part 2) - EDM/2 - Jul 1996 - Volume 4 
  1145. Issue 6 
  1146.  
  1147.  
  1148. ΓòÉΓòÉΓòÉ 5.4. Concluding Remarks ΓòÉΓòÉΓòÉ
  1149.  
  1150.  Concluding Remarks 
  1151.  
  1152. Neither of the classes nor AStatusLine have a copy constructor.  Because some 
  1153. data members are just pointers to a memory block allocated during runtime, you 
  1154. must not copy objects of these classes.  The reason is that the default copy 
  1155. constructor can't handle those members in the correct way. 
  1156.  
  1157. In AFile, there are some members set but never used.  I included them for 
  1158. future methods, e.g like getOpenFlags, getOpenMode. 
  1159.  
  1160. You might miss the two messages left defined in Part I, MYM_PROCESS_START and 
  1161. MYM_PROCESS_END. 
  1162.  
  1163. In principle they can be posted by AEditFile::read and AEditFile::write, but I 
  1164. think they should be posted by the main object which starts the process because 
  1165. one of the values passed by the MYM_PROCESS_START message is a resource id.  If 
  1166. you want to use the AEditFile class in several projects and use AEditFile::read 
  1167. and AEditFile::write for posting the start message, you must take care that 
  1168. there is always a resource defined which matches the resource id passed in this 
  1169. members. 
  1170.  
  1171. The main object, which uses the classes shown in part I and part II in a 
  1172. (really) simple multi-threaded environment, will be the contents of the last 
  1173. part. 
  1174.  
  1175. A Progress-indicating Status Line in C++ (Part 2) - EDM/2 - Jul 1996 - Volume 4 
  1176. Issue 6 
  1177.  
  1178.  
  1179. ΓòÉΓòÉΓòÉ 6. The Codesmith's Library ΓòÉΓòÉΓòÉ
  1180.  
  1181.  
  1182. ΓòÉΓòÉΓòÉ 6.1. The Codesmith's Library ΓòÉΓòÉΓòÉ
  1183.  
  1184.  The Codesmith's Library 
  1185.  
  1186. Written by Joe Wyatt 
  1187.  
  1188. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1189.  
  1190. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1191.  
  1192. In The Codesmith's Library, I focus on development books and materials.  I 
  1193. write this column from the point of view of an intermediate PM C programmer and 
  1194. intermediate REXX programmer.  Pick up whichever book strikes your fancy, and 
  1195. join the growing group of people following our PM programming columns.  I have 
  1196. already reviewed a number of beginner books, and will try to concentrate more 
  1197. on intermediate techniques and special topics from now on. 
  1198.  
  1199. Please send me your comments and thoughts so that I can make this column what 
  1200. you want it to be.  I read and respond to all mail. 
  1201.  
  1202. Message Functions, OS/2 Quick Reference Library Volume 2 is possibly the only 
  1203. book on the market which covers all the OS/2 messages.  It is volume 2 of a 6 
  1204. volume series. 
  1205.  
  1206. The Codesmith's Library - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1207.  
  1208.  
  1209. ΓòÉΓòÉΓòÉ 6.2. Errata ΓòÉΓòÉΓòÉ
  1210.  
  1211.  Errata 
  1212.  
  1213. Yet again I am going to trumpet The OS/2 API Project.  It is getting quite 
  1214. useful, with more than 36 APIs on site, as well as over 75 #define's.  Have a 
  1215. look, and if you have the time, chip in by writing up one or more APIs and 
  1216. sending them to me.  I will also happily listen to any and all suggestions 
  1217. regarding layout and format.  The more people help out, the quicker this 
  1218. project will become very helpful.  The INF version is now out, although it is a 
  1219. touch behind the HTML version.  Check it out at [Editor's note:  EDM/2 has 
  1220. "absorbed" the OS/2 API Project, although it continues to be a separate entity. 
  1221. It's location has changed, however, and it is reflected in the URL below.]: 
  1222.  
  1223. http://www.iqpac.com/edm2/os2api/index.html 
  1224.  
  1225. The OS/2 API Project aims at documenting the entire OS/2 API and distributing 
  1226. it as a free document, to help out people who can't afford the IBM 
  1227. documentation, or have something better to spend their money on.  I figure it 
  1228. can only help the number of OS/2 programs out there if more people have access 
  1229. to this information. 
  1230.  
  1231. The Codesmith's Library - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1232.  
  1233.  
  1234. ΓòÉΓòÉΓòÉ 6.3. OS/2 Quick Reference Library, Volume 2, Message Functions ΓòÉΓòÉΓòÉ
  1235.  
  1236.  OS/2 Quick Reference Library, Volume 2, Message Functions 
  1237.  
  1238. This is the second book in the same series as WIN Functions, OS/2 Quick 
  1239. Reference Library Volume 1, which I previously reviewed.  Here are the chapter 
  1240. headings: 
  1241.  
  1242.       1.  How to Use This Book 
  1243.       2.  Notebook Control Messages 
  1244.       3.  Button Control Messages 
  1245.       4.  Combo Box Messages 
  1246.       5.  Container Control Messages 
  1247.       6.  Direct Manipulation Messages 
  1248.       7.  Entry Field Messages 
  1249.       8.  File Dialog Messages 
  1250.       9.  Font Dialog Messages 
  1251.       10.  Help Manager Messages 
  1252.       11.  List Box Control Messages 
  1253.       12.  Multiline Entry Messages 
  1254.       13.  Menu Control Messages 
  1255.       14.  Profile Messages 
  1256.       15.  Scroll Bar Messages 
  1257.       16.  Slider Control Messages 
  1258.       17.  Static Control Messages 
  1259.       18.  Spin Button Messages 
  1260.       19.  Title Bar Messages 
  1261.       20.  Value Set Control Messages 
  1262.       21.  Window Messages 
  1263.       Appendix A:   Data Type Structures 
  1264.       Appendix B:   Error Code Definitions 
  1265.       Appendix C:   Container Notification Codes 
  1266.  
  1267.  As you can see from the picture of this book, it is bound with ring binding. 
  1268.  All reference books should be bound this way, or at least with the 
  1269.  O'Reilly-style binding, but unfortunately this is rarely the case.  `Nuff 
  1270.  said. 
  1271.  
  1272.  At the start of each chapter, there is a little section with cross-references 
  1273.  to other related messages.  Unfortunately, there are no page numbers given, 
  1274.  only which chapter they are in. 
  1275.  
  1276.  Each message has a title, a brief description, message declarations (ie. 
  1277.  param1, param2, and reply), parameters, returns, remarks and default 
  1278.  processing.  The remarks section is where you will probably spend most of your 
  1279.  reading time, but unfortunately, I find that it is not always complete.  Many, 
  1280.  if not most, of these messages are sent by a call to some API, but this 
  1281.  reference does not discuss these related APIs.  In addition, some special 
  1282.  properties of certain messages are not discussed either, such as the fact that 
  1283.  sending MM_SETDEFAULTITEMID actually converts a cascade menu to a conditional 
  1284.  cascade menu.  Even though this is a message reference, I find myself wishing 
  1285.  for a stronger connection to the related APIs.  In general, however, the 
  1286.  descriptions are quite good, if occasionally incomplete. 
  1287.  
  1288.  The layout of the chapters is logical, being alphabetical by message name 
  1289.  though the whole book.  The lack of cross-reference page-numbers is a bother, 
  1290.  though.  As an example, if you are looking for the LM_SEARCHSTRING message, 
  1291.  you will find it on page 186.  At the start of the chapter, page 175, there 
  1292.  are references to other related messages, such as WM_CONTROL.  To find this, 
  1293.  you must then flip around until you find it on page 372.  The fact that the 
  1294.  messages are alphabetical through the whole book helps somewhat, but this is 
  1295.  still 3 separate searches though the pages.  This could have been minimized by 
  1296.  following the same format as the OS/2 Warp API series, with page numbers 
  1297.  listed, or even the same as the earlier book in the same series! 
  1298.  
  1299.  Again, this book is not a tutorial by any means, but it does provide a 
  1300.  description for every message I have ever come across, which is more than any 
  1301.  other book on the market can say. 
  1302.  
  1303.  I recommend this book, but despite the fact that it is competent, it misses 
  1304.  the opportunity to go that extra mile and become the great reference book that 
  1305.  some of its companion books are.  I suspect that it will be surpassed by the 
  1306.  next message book on the market, unless it is updated first. 
  1307.  
  1308.  The Codesmith's Library - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1309.  
  1310.  
  1311. ΓòÉΓòÉΓòÉ 6.4. Summary ΓòÉΓòÉΓòÉ
  1312.  
  1313.  Summary 
  1314.  
  1315. This little reference book has the only message descriptions out there 
  1316. currently, and it is quite invaluable as such.  Nonetheless, there are a number 
  1317. of convenience features missing, such as page number references, see also 
  1318. sections, coloured chapters (on the page ends, a la Sidekick, see volume 4 
  1319. issue 2), and descriptions of related functions.  It is good, but due to the 
  1320. lack of these items, I feel that a newer book could quickly eclipse this one. I 
  1321. rate it a B. 
  1322.  
  1323. The Codesmith's Library - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1324.  
  1325.  
  1326. ΓòÉΓòÉΓòÉ 6.5. Book Reviewed ΓòÉΓòÉΓòÉ
  1327.  
  1328.  Book Reviewed 
  1329.  
  1330.      Message  Functions, OS/2 Quick Reference Library Volume 2, Scholin 
  1331.  
  1332.  
  1333.         -  Van Nostrand Reinhold, ISBN 0-442-01898-3, $20US, $30CAN. 
  1334.  
  1335.            Note that Van Nostrand Reinhold has sold its OS/2 library to John 
  1336.            Wiley  and  Sons,  and hence this  book  will  now  be obtainable 
  1337.            through John Wiley, rather than VNR. 
  1338.         -  Intended audience: PM C Programmers 
  1339.         -  Mark: B 
  1340.  
  1341.       A good reference, but misses out on several convenience features.  This 
  1342.       is the only message reference on the market currently, to my knowledge, 
  1343.       so it wins by default. 
  1344.  
  1345.  NOTES 
  1346.  
  1347.  Please note that books aimed at different audiences should only be compared 
  1348.  with great care, if at all.  I intend to concentrate on the strong points of 
  1349.  the books I review, but I will point out any weaknesses in a constructive 
  1350.  manner. 
  1351.  
  1352.  LEGEND 
  1353.  
  1354.  BOOK:  The name of the book, and the author(s) 
  1355.  
  1356.  PUBLISHING INFORMATION:  Publishing company, ISBN, and approximate price. 
  1357.  
  1358.  AUDIENCE:  This is a description of the audience I think the book targets 
  1359.  best.  This is not intended as gospel, just a guideline for people not 
  1360.  familiar with the book. 
  1361.  
  1362.  MARK:  My opinion of the success of the book's presentation, and how well it 
  1363.  targets its audience.  Technical content, accuracy, organization, readability, 
  1364.  and quality of index all weigh heavily here, but the single most important 
  1365.  item is how well the book covers what it says it covers.  Many books try to 
  1366.  cover too much, and get a lower mark as a result. 
  1367.  
  1368.   +------+-------------------------------------------------------------------------+
  1369.   | MARK | DESCRIPTION                                                             |
  1370.   +------+-------------------------------------------------------------------------+
  1371.   | A+   | Ground-breaking, all-around outstanding book                            |
  1372.   | A    | Excellent book.  This is what I want to see happen a lot                |
  1373.   | A-   | Excellent book with minor flaws                                         |
  1374.   | B+   | Very good book with minor flaws or omissions                            |
  1375.   | B    | Good book with some flaws and omissions                                 |
  1376.   | B-   | Good book, but in need of improvement                                   |
  1377.   | C+   | Mediocre book with some potential, but in need of some updating         |
  1378.   | C    | Mediocre book with some good sections, but badly in need of fixing      |
  1379.   | C-   | Mediocre book, little good material, desperately in need of an overhaul |
  1380.   | D    | Don't buy this book unless you need it, and nothing else exists         |
  1381.   | F    | Don't buy this book.  Period                                            |
  1382.   +------+-------------------------------------------------------------------------+
  1383.  
  1384.  COMMENTS:  This is a very brief summary of the review proper. 
  1385.  
  1386.  The Codesmith's Library - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1387.  
  1388.  
  1389. ΓòÉΓòÉΓòÉ 6.6. Coming Up ΓòÉΓòÉΓòÉ
  1390.  
  1391.  Coming Up 
  1392.  
  1393. I do not yet have a book for next month.  I have been promised several of the 
  1394. books below, however. 
  1395.  
  1396. Other books I would like to review: 
  1397.  
  1398. The Art of OS/2 Warp Programming, Panov, Salomon, Panov - I have recently 
  1399. noticed that this has been out for a while.  Hint, hint, Larry. [Lest anyone 
  1400. think I am stingy, I finally got in touch with my editor - after much confusion 
  1401. and miscommunication - and a copy is on the way.  - Larry] 
  1402.  
  1403. Objects for OS/2, Tate - This sounds interesting, but is it C or C++? Time will 
  1404. tell. 
  1405.  
  1406. The Design of OS/2, 2nd Edition, Kogan and Deitel - I am having trouble getting 
  1407. a copy of this, so if anyone can help, please do.  A 1st edition would do me 
  1408. fine too. 
  1409.  
  1410. OS/2 C++ Class Library:  Power GUI Programming with CSet++, Law, Leong, Love 
  1411. and Tsuji - This is on the way I am told. 
  1412.  
  1413. OS/2 Presentation Manager GPI, 2nd edition, Winn - I really would like to 
  1414. review this soon, as I am coming across some stuff that the old one doesn't 
  1415. handle in an up-to-date manner, and want to see what the new one is all about. 
  1416.  
  1417. Visual Age:  Concepts and Features, ?  - This sounds interesting. 
  1418.  
  1419. If anyone has a book they want to see reviewed, I will be happy to oblige. Just 
  1420. mail me and tell me which.  Publishers can send me books at the address on my 
  1421. personal page at the end of the magazine, and I will review all OS/2 
  1422. development-related and advanced user books I receive. 
  1423.  
  1424. The Codesmith's Library - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1425.  
  1426.  
  1427. ΓòÉΓòÉΓòÉ 7. REXX Inside and Out ΓòÉΓòÉΓòÉ
  1428.  
  1429.  
  1430. ΓòÉΓòÉΓòÉ 7.1. REXX Inside and Out ΓòÉΓòÉΓòÉ
  1431.  
  1432.  REXX Inside and Out 
  1433.  
  1434. Written by Carsten Whimster 
  1435.  
  1436. Introduction 
  1437.  
  1438. Several years ago I wrote programs in the SAS language to interrogate the MVS 
  1439. operating system's resources and configuration.  Because of the interpretive 
  1440. nature of SAS, it was possible for one program to write new sections of code 
  1441. based on elements defined to the system, place them in temporary data sets, and 
  1442. then include them later in the program.  Now instead of needing to keep static 
  1443. tables of resource information that were manually updated, I was able to 
  1444. provide a maintenance free application that could adjust itself to changes in 
  1445. the operating environment.  I named the program SAS007 (007 as in James Bond) 
  1446. because of its sneaky nature.  "You mean your program writes itself, executes, 
  1447. and then goes away so that there is no chance to debug it or see what was going 
  1448. on?", a co-worker asked one day while examining my program and slowly shaking 
  1449. her red head.  "Slick, huh?", I boasted.  She handed my program back, and with 
  1450. a chuckle she added, "I never really did like dynamically self-violating code 
  1451. myself." 
  1452.  
  1453. I've learned quite a bit since that time, but the old temptations return when 
  1454. dealing with REXX and automation.  "REXX is an interpretive language, right?", 
  1455. I ask myself.  "Why not write some of that self-violating stuff that will adapt 
  1456. to the variations in the system?  I could stuff some dynamic code into a file 
  1457. and then...  No WAIT!  I could put a bunch of code into a buffer and invoke the 
  1458. INTERPRET instruction!  Yeah.  That's the ticket!"  Usually it's about now that 
  1459. reality hits me and I realize that even though the language supports it, it 
  1460. might not be such a good idea to use it. 
  1461.  
  1462. Although we will discuss the INTERPRET instruction, this column is dedicated to 
  1463. the avoidance of "dynamically self-violating" code. 
  1464.  
  1465. REXX Inside and Out - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1466.  
  1467.  
  1468. ΓòÉΓòÉΓòÉ 7.2. Interpret ΓòÉΓòÉΓòÉ
  1469.  
  1470.  Interpret 
  1471.  
  1472. INTERPRET is one of those statements that if you need it you have to have it, 
  1473. but you pray that you will never need it.  At least that is what I have heard. 
  1474. In my seven years of REXX programming, although I have played with INTERPRET, I 
  1475. have never "needed" the instruction badly enough to use it in a production 
  1476. level program.  The statement usually renders the program unmaintainable by 
  1477. anyone but its author unless the author has slept since the program was 
  1478. written.  (if the author has slept since the program's conception there is a 
  1479. great chance that he/she will be unable to easily update the code) "Couldn't 
  1480. you just fully document the use of this instruction in your program so that its 
  1481. intended purpose is apparent?", you ask.  "Well...  I have to believe that 
  1482. anybody who would not find away around using this instruction would not bother 
  1483. to comment their code."  (That last statement was placed in quotes because it 
  1484. is certain that there are people out there who have had a valid need for this 
  1485. instruction and have taken great pains to comment the reasons for its use. 
  1486. Call it a gross generality if you would like.)  There is a further reason to 
  1487. refrain from the use of the INTERPRET instruction.  The IBM compilers for REXX 
  1488. (no, they don't exist for OS/2 at this time and may never) do not support it. 
  1489.  
  1490. So why am I spending time telling you about an instruction that is at least as 
  1491. wicked as a GOTO?  Can you say "Quick and Dirty programming?"  I thought you 
  1492. could.  When developing one shot tools or tools for self use this can solve 
  1493. some problems. 
  1494.  
  1495. While an entire program section can be placed in a buffer and used dynamically 
  1496. with the INTERPRET instruction, our example will only interpret one instruction 
  1497. at a time. 
  1498.  
  1499. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1500.  
  1501.  
  1502. /* quick and dirty calculator */
  1503. x = 0     /* initialize displayed variables */
  1504. y = 0
  1505. z = 0
  1506.  
  1507. Say "x =" x     /* display variable content and availability */
  1508. Say "y =" y
  1509. Say "z =" z
  1510. call charout ,"===>  "        /* input prompt */
  1511. pull stuff               /* get equation   */
  1512.  
  1513. do while (stuff <> "EXIT")
  1514.     INTERPRET stuff      /* evaluate equation */
  1515.     Say "x =" x
  1516.     Say "y =" y
  1517.     Say "z =" z
  1518.     call charout ,"===>  "
  1519.     pull stuff
  1520. end
  1521. exit
  1522.  
  1523. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1524.  
  1525. Figure 1) A simple example of INTERPRET. 
  1526.  
  1527. The above program accepts user input such as "x = y + 56 / 8.3", evaluates the 
  1528. expressions with the INTERPRET instruction, displays the results, and gathers 
  1529. more input until the word "exit" is entered; or the word "barf" is entered; or 
  1530. the phrase "I'll bet you can't handle this input" is entered. This program 
  1531. would be quite a bit longer were it to take the time to evaluate the equation 
  1532. on its own instead of using INTERPRET.  There is one other interesting feature 
  1533. of this bullet proof code that is a bit off of the topic that should be noted 
  1534. here. 
  1535.  
  1536. Many people desire a prompt line before their "pull" instruction.  This is 
  1537. accomplished with the use of charout() with a null parameter for the file name. 
  1538.  
  1539. It was mentioned earlier that an entire program section could be placed into a 
  1540. variable and included as part of your program with the INTERPRET instruction. 
  1541. To accomplish this nasty habit, each statement must be delimited by a 
  1542. semicolon. 
  1543.  
  1544. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1545.  
  1546.  
  1547.   :
  1548. buffer = "Var" || count "=" count"; say Var" || count
  1549. INTERPRET buffer
  1550.   :
  1551.  
  1552. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1553.  
  1554. The above lines assign a value to a variable created by the text "Var" and the 
  1555. value of the variable "count" and display the contents of this new data. This 
  1556. example was included to show multiple program statements within a single 
  1557. INTERPRET, but also included to show a common misuse of this instruction. REXX 
  1558. contains a function that will perform this variable manipulation without the 
  1559. smoke and mirrors of INTERPRET. 
  1560.  
  1561. REXX Inside and Out - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1562.  
  1563.  
  1564. ΓòÉΓòÉΓòÉ 7.3. Value() ΓòÉΓòÉΓòÉ
  1565.  
  1566.  Value() 
  1567.  
  1568. The value function has three arguments by definition: 
  1569.  
  1570. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1571.  
  1572.  
  1573. target = Value( variable_name, new_value, selector );
  1574.  
  1575. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1576.  
  1577. variable_name - since the name of a variable is an argument, variables can be 
  1578. created dynamically.  The previous use of INTERPRET created a variable, "Var" 
  1579. || count.  Value() could be used to create this variable by passing the same 
  1580. information in the first argument. 
  1581.  
  1582. new_value - the variable created or addressed by the first argument is assigned 
  1583. whatever value is referenced by this argument. 
  1584.  
  1585. selector - this is a special argument and for basic variable manipulation 
  1586. should contain a null value.  As far as I can determine, the only valid 
  1587. non-null value for this argument is OS2ENVIRONMENT.  When OS2ENVIRONMENT is 
  1588. used, the current session environment is interrogated to solve the value 
  1589. request. 
  1590.  
  1591. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1592.  
  1593.  
  1594. current_path = Value("PATH", , "OS2ENVIRONMENT")
  1595.  
  1596. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1597.  
  1598. The above call to value() would retrieve the value of the session's current 
  1599. "PATH" environment variable but would not change its value because the 
  1600. new_value argument was left blank. 
  1601.  
  1602. returns - value() returns the value of the variable referenced by the first 
  1603. argument before the new value is assigned. 
  1604.  
  1605. The last INTERPRET example could have been replaced with the more efficient and 
  1606. compiler friendly 
  1607.  
  1608. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1609.  
  1610.  
  1611.   :
  1612. call value "Var" || count, count
  1613. Say value("Var" || count)
  1614.   :
  1615.  
  1616. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1617.  
  1618. A further example: 
  1619.  
  1620. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1621.  
  1622.  
  1623.   :
  1624. drives = SysDriveMap("C:", "USED") /* get list of available DASD */
  1625. do words( drives )
  1626.      parse var drives singleton drives        /* loop through drive letters */
  1627.      info = SysDriveInfo( singleton )         /* get disk drive information */
  1628.      call value word(info, 4), word(info, 2)  /* create var with disk name */
  1629. end
  1630.   :
  1631.  
  1632. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1633.  
  1634. Figure 2)  A simple example of Value(). 
  1635.  
  1636. The above program segment creates a variable for each disk drive starting with 
  1637. C: and assigns it the value of the number of freespace bytes left on the drive. 
  1638. This is a less contrived use of Value(), but it still is too complex. 
  1639.  
  1640. REXX Inside and Out - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1641.  
  1642.  
  1643. ΓòÉΓòÉΓòÉ 7.4. Reality ΓòÉΓòÉΓòÉ
  1644.  
  1645.  Reality 
  1646.  
  1647. While Value() is certainly a nifty little function, the only use of it that can 
  1648. be found in programs that leave my machine are to reference the OS/2 
  1649. environment.  REXX's compound variable structures are powerful enough to thwart 
  1650. any of my contrived "needs" for the value() function. 
  1651.  
  1652. The previous Value() example could have avoided any confusing use of the 
  1653. Value() function by being coded as follows: 
  1654.  
  1655. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1656.  
  1657.  
  1658.   :
  1659. drives = sysDriveMap("C:", "USED")
  1660. do words( drives )
  1661.     parse var drives singleton drives
  1662.     info = SysDriveInfo( singleton )
  1663.     drive_name = word( info, 4 )
  1664.  
  1665.     drive_free_space.drive_name = word( info, 2 )
  1666. end
  1667.   :
  1668.  
  1669. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1670.  
  1671. Figure 3)  Cleanup up the Value() example. 
  1672.  
  1673. Four out of five programmers agree that this example is clearer than the last 
  1674. Value() example.  "But gee, Uncle Bob, aren't compound variables slow?", you 
  1675. might ask. 
  1676.  
  1677. REXX's variable pools are kept in efficient tree structures so that their 
  1678. manipulation does not slow down the program.  If speed is really a concern it 
  1679. might be noted that this example also eliminates a function call! 
  1680.  
  1681. REXX Inside and Out - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1682.  
  1683.  
  1684. ΓòÉΓòÉΓòÉ 7.5. Conclusion ΓòÉΓòÉΓòÉ
  1685.  
  1686.  Conclusion 
  1687.  
  1688. REXX is a powerful language that can support all of the bad programming 
  1689. practices of my youth.  "Dynamically self- violating code" is even easier to 
  1690. create in REXX than it was in the SAS language.  So why not go let all of this 
  1691. power go to my head and just start including INTERPRET statements and Value() 
  1692. calls any place I think it might be "neat"? 
  1693.  
  1694. Gather around, Kiddies, and let old Uncle Bob tell you a story.  Remember 
  1695. SAS007?  That slick piece of code ran daily for a couple of years after I left 
  1696. the company for which it was written.  One day (ok, probably over a weekend) 
  1697. the version of MVS was upgraded a to a new version (MVS/XA).  This version 
  1698. changed the location of some of the information that SAS007 was gathering. 
  1699. Instead of being able to make some simple code changes to update the program to 
  1700. run with the new operating system version it was labeled as spooky and tossed 
  1701. aside like a useless piece of garbage.  So all of the time that the company had 
  1702. invested for me to write that program was wasted because it had to be written 
  1703. again. 
  1704.  
  1705. As we've seen here, straight forward code can even be more efficient than 
  1706. "slick" code.  Most programmers not only desire their work to be efficient, but 
  1707. long lived.  Let's face it.  Our programs are the main tools a programmer has 
  1708. to make a name for himself.  Slick code will make a name for the programmer. 
  1709. What will that name change to when the code breaks and the company that paid 
  1710. for its development gets to keep both pieces? 
  1711.  
  1712. REXX Inside and Out - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1713.  
  1714.  
  1715. ΓòÉΓòÉΓòÉ 8. The Codesmith's Library ΓòÉΓòÉΓòÉ
  1716.  
  1717.  
  1718. ΓòÉΓòÉΓòÉ 8.1. The Codesmith's Library ΓòÉΓòÉΓòÉ
  1719.  
  1720.  The Codesmith's Library 
  1721.  
  1722. Written by Carsten Whimster 
  1723.  
  1724. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1725.  
  1726. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  1727.  
  1728. In The Codesmith's Library, I focus on development books and materials.  I 
  1729. write this column from the point of view of an intermediate PM C programmer and 
  1730. intermediate REXX programmer.  Pick up whichever book strikes your fancy, and 
  1731. join the growing group of people following our PM programming columns.  I have 
  1732. already reviewed a number of beginner books, and will try to concentrate more 
  1733. on intermediate techniques and special topics from now on. 
  1734.  
  1735. Please send me your comments and thoughts so that I can make this column what 
  1736. you want it to be.  I read and respond to all mail. 
  1737.  
  1738. This mini review will be an occasional column which covers development-related 
  1739. books that are not OS/2-specific.  It will not cover books that are specific to 
  1740. any O/S at all, but will rather cover books of importance to the developer 
  1741. segment in general.  Because these books are not OS/2 specific, I will keep the 
  1742. review shorter than a full review, and will just focus on describing the book 
  1743. in general strokes. 
  1744.  
  1745. Writing Solid Code is the best non-OS/2 book I have read in a long time. It 
  1746. focuses on the prevention of bugs. 
  1747.  
  1748. The Codesmith's Library - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1749.  
  1750.  
  1751. ΓòÉΓòÉΓòÉ 8.2. Writing Solid Code ΓòÉΓòÉΓòÉ
  1752.  
  1753.  Writing Solid Code 
  1754.  
  1755. This book maybe one of the most important books to come out in a long time, 
  1756. especially right now.  It focuses on how to avoid writing bugs, how to prevent 
  1757. bugs, and how to fix bugs properly.  Here are the chapters: 
  1758.  
  1759.       1.  A Hypothetical Compiler 
  1760.       2.  Assert Yourself 
  1761.       3.  Fortify Your Subsystems 
  1762.       4.  Step Through Your Code 
  1763.       5.  Candy-Machine Interfaces 
  1764.       6.  Risky Business 
  1765.       7.  Treacheries of the Trade 
  1766.       8.  The Rest is Attitude 
  1767.       Epilogue: Where Do You Go from Here? 
  1768.       Appendix A:   Coding Checklists 
  1769.       Appendix B:   Memory Logging Routines 
  1770.       Appendix C:   Answers 
  1771.  
  1772.  It is interesting that this book should come from Microsoft.  There have been 
  1773.  many public statements by (sometimes anonymous) officials at Microsoft, saying 
  1774.  things like "you only ever have to get 90% of the product working", in 
  1775.  addition to the extraordinary bugginess of the initial release of Word 6.0, 
  1776.  and on and on.  It is interesting to note that Maguire no longer seems to work 
  1777.  for Microsoft.  I can't offer any explanation for these seeming 
  1778.  contradictions, only suggest that this book was ignored by the programmers of 
  1779.  Word and Windows 95, and followed strictly by the NT programmers <grin>. 
  1780.  
  1781.  The book starts with a short intro, which among other things encourages the 
  1782.  use of Hungarian Notation for variable naming.  I was able to find these 
  1783.  notations on the web fairly easily by searching for "Hungarian AND Notation" 
  1784.  on Yahoo and Web Crawler. 
  1785.  
  1786.  Chapter 1 discusses a hypothetical compiler which is able to catch all 
  1787.  problems in your code.  Maguire goes on to explain that of all the most 
  1788.  desirable error messages, many are already implemented in modern compilers, 
  1789.  but most people turn off this error detection because they either do not 
  1790.  understand the message, or they code in unsafe ways and find the messages 
  1791.  annoying.  He goes on to recommend the use of lint and other tools, on a 
  1792.  religious basis.  At the end of this and all the chapters, there is a short 
  1793.  section with questions to encourage the reader to think more about the 
  1794.  underlying issues of the chapter.  There is even a little suggested project 
  1795.  for the reader to perform, if he or she is very enthusiastic. 
  1796.  
  1797.  Chapter 2 weighs the pros and cons of the standard C library's assert, and 
  1798.  then goes on to define a better one.  This is then demonstrated with several 
  1799.  code examples.  Again, the emphasis here is on the prevention and automatic 
  1800.  detection of bugs.  Documentation of tricky code is also recommended, again 
  1801.  with some real examples.  Most of the examples in this book are taken from the 
  1802.  real process of developing Excel, mostly on the Mac.  Maguire started as a 
  1803.  programmer for Excel, and later moved up to be a team lead.  The assert 
  1804.  routine developed by Maguire is used in a variety of different situations to 
  1805.  detect a multitude of hard-to-spot bugs lurking in the wings of the 
  1806.  application. 
  1807.  
  1808.  Fortifying your subsystems is the theme of chapter 3. The intent here is that 
  1809.  you should provide debug-only double- checks of important algorithms, ensure 
  1810.  that all code runs in testing, destroying garbage, initializing memory, and so 
  1811.  on.  These checks mostly occur at debug-time only, of course, so as to avoid 
  1812.  slowing down the gold code. 
  1813.  
  1814.  Stepping through your code with a debugger is the topic of chapter 4. This 
  1815.  seemingly time-wasting trick will save lots of time debugging code that never 
  1816.  worked quite right in the first place, but it has to be done when the code was 
  1817.  written, and the ideas clear in the mind of the programmer, of course, not two 
  1818.  years later. 
  1819.  
  1820.  In chapter 5, Maguire makes an interesting comparison between function 
  1821.  interfaces and candy-machine interfaces.  Writing function interfaces in such 
  1822.  a way as to be unambiguous is more important than apparent at first, and even 
  1823.  the standard C library is rife with examples of poor interfaces.  One example 
  1824.  is getchar() which returns, of course, an int!  Separating error codes from 
  1825.  return values is but one piece of advice you will find in this chapter. 
  1826.  
  1827.  Risk, and proper use of the language is the major topic of chapter 6. It is 
  1828.  amazing how many programmers will code a straight-forward task in a quirky, 
  1829.  non-portable way, only because it seems more clever or faster, when in fact it 
  1830.  is neither.  Discover other language tips in chapter 6. 
  1831.  
  1832.  Resisting the temptation of writing clever, but obscure code is one of the 
  1833.  focuses of chapter 7. Not referencing memory already freed is yet another tip, 
  1834.  which seems all to obvious, but which many programmers do nevertheless.  Treat 
  1835.  input parameters as read-only, output-parameters as write- only, and so on. 
  1836.  Not falling into the trap of thinking that tight C means tight machine code is 
  1837.  yet another example.  Use the debugger to get a feel for what code the 
  1838.  compiler generates here.  Finally, a little-realized aspect of development is 
  1839.  that novice programmers tend to be the ones who maintain code, so experienced 
  1840.  programmers should resist the temptation to write difficult to understand 
  1841.  code, in all but the most extreme situations, since this code will not be 
  1842.  understood, and thus most likely be ripped out by maintenance programmers. 
  1843.  
  1844.  In the last chapter we are told to get the correct attitude to go along with 
  1845.  all our new-found knowledge of bugs.  Bugs never just disappear by themselves, 
  1846.  for example, yet many programmers use this as an excuse.  Do not add extra 
  1847.  unnecessary features to products just because they are easy to add either, 
  1848.  since this new (easy) code is yet another spot where bugs can hide and bite 
  1849.  you from.  This last chapter has many other great suggestions. 
  1850.  
  1851.  The real strength of this book is that the tips themselves often sound silly, 
  1852.  derogatory, and obvious, but in the context of the examples given, I came to 
  1853.  realize again and again that I too had fallen for many of these traps. Read 
  1854.  the whole book, page for page, and follow the advice given. 
  1855.  
  1856.  The Codesmith's Library - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1857.  
  1858.  
  1859. ΓòÉΓòÉΓòÉ 8.3. Summary ΓòÉΓòÉΓòÉ
  1860.  
  1861.  Summary 
  1862.  
  1863. This book is very important, and every serious developer should take a jet, not 
  1864. run, to the nearest bookstore to pick up a copy.  It has an incredible array of 
  1865. methods for avoiding and fighting bugs, and in these bug- ridden, bloated code 
  1866. days, this is more important than ever before in history.  Do not assume that 
  1867. you can do the things I mentioned in this review, and be done. They are only 
  1868. representative of what Maguire discusses.  This books is so full of tricks and 
  1869. explanations that you just do not want to miss, and this book is really cheap 
  1870. and well worth the money.  A+. 
  1871.  
  1872. The Codesmith's Library - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1873.  
  1874.  
  1875. ΓòÉΓòÉΓòÉ 8.4. Book Reviewed ΓòÉΓòÉΓòÉ
  1876.  
  1877.  Book Reviewed 
  1878.  
  1879.      Writing Solid Code, Maguire 
  1880.  
  1881.  
  1882.         -  Microsoft Press, ISBN 1-55615-551-4, $US24.95, $32.95CAN, UK21.95. 
  1883.         -  Intended audience: C/C++ Programmers 
  1884.         -  Mark: A+ 
  1885.  
  1886.       A great little cheap book on avoiding, fighting, and automatically 
  1887.       preventing bugs.  Every programmer in the world should own a copy of this 
  1888.       great book, and should use it religiously. 
  1889.  
  1890.  NOTES 
  1891.  
  1892.  Please note that books aimed at different audiences should only be compared 
  1893.  with great care, if at all.  I intend to concentrate on the strong points of 
  1894.  the books I review, but I will point out any weaknesses in a constructive 
  1895.  manner. 
  1896.  
  1897.  LEGEND 
  1898.  
  1899.  BOOK:  The name of the book, and the author(s) 
  1900.  
  1901.  PUBLISHING INFORMATION:  Publishing company, ISBN, and approximate price. 
  1902.  
  1903.  AUDIENCE:  This is a description of the audience I think the book targets 
  1904.  best.  This is not intended as gospel, just a guideline for people not 
  1905.  familiar with the book. 
  1906.  
  1907.  MARK:  My opinion of the success of the book's presentation, and how well it 
  1908.  targets its audience.  Technical content, accuracy, organization, readability, 
  1909.  and quality of index all weigh heavily here, but the single most important 
  1910.  item is how well the book covers what it says it covers.  Many books try to 
  1911.  cover too much, and get a lower mark as a result. 
  1912.  
  1913.   +------+-------------------------------------------------------------------------+
  1914.   | MARK | DESCRIPTION                                                             |
  1915.   +------+-------------------------------------------------------------------------+
  1916.   | A+   | Ground-breaking, all-around outstanding book                            |
  1917.   | A    | Excellent book.  This is what I want to see happen a lot                |
  1918.   | A-   | Excellent book with minor flaws                                         |
  1919.   | B+   | Very good book with minor flaws or omissions                            |
  1920.   | B    | Good book with some flaws and omissions                                 |
  1921.   | B-   | Good book, but in need of improvement                                   |
  1922.   | C+   | Mediocre book with some potential, but in need of some updating         |
  1923.   | C    | Mediocre book with some good sections, but badly in need of fixing      |
  1924.   | C-   | Mediocre book, little good material, desperately in need of an overhaul |
  1925.   | D    | Don't buy this book unless you need it, and nothing else exists         |
  1926.   | F    | Don't buy this book.  Period                                            |
  1927.   +------+-------------------------------------------------------------------------+
  1928.  
  1929.  COMMENTS:  This is a very brief summary of the review proper. 
  1930.  
  1931.  The Codesmith's Library - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1932.  
  1933.  
  1934. ΓòÉΓòÉΓòÉ 8.5. Coming Up ΓòÉΓòÉΓòÉ
  1935.  
  1936.  Coming Up 
  1937.  
  1938. My next mini review will be Code Complete. 
  1939.  
  1940. Other books I have: 
  1941.  
  1942. Code Complete, McConnell - The next book in this series from Microsoft Press 
  1943.  
  1944. Algorithms in C++, Sedgewick - This classic has a place in every C++ 
  1945. developer's library 
  1946.  
  1947. Zen of Code Optimization, Abrash - An exiting book about writing fast code the 
  1948. right way 
  1949.  
  1950. Other books I would like to review: 
  1951.  
  1952. Enough Rope to Shoot Yourself in the Foot, Holub 
  1953.  
  1954. Software Testing, Roper 
  1955.  
  1956. Error Coding Cookbook, Rorabaugh 
  1957.  
  1958. Applied Cryptography, Schneier 
  1959.  
  1960. Software Reuse, Karlsson 
  1961.  
  1962. If anyone has a book they want to see reviewed, I will be happy to oblige. Just 
  1963. mail me and tell me which.  Publishers can send me books at the address on my 
  1964. personal page at the end of the magazine, and I will review all OS/2 
  1965. development- related and advanced user books I receive. 
  1966.  
  1967. The Codesmith's Library - EDM/2 - Jul 1996 - Volume 4 Issue 6 
  1968.  
  1969.  
  1970. ΓòÉΓòÉΓòÉ 9. Contributors to this Issue ΓòÉΓòÉΓòÉ
  1971.  
  1972. Are You a Potential Author? 
  1973.  
  1974. We are always looking for authors.  If you have a topic about which you would 
  1975. like to write, send a brief description of the topic electronically to any of 
  1976. the editors by the 15th of the month before the month in which your article 
  1977. will appear.  This alerts us that you will be sending an article so that we can 
  1978. plan the issue layout accordingly. 
  1979.  
  1980. After you have done this, read the latest copy of the Article Submission 
  1981. Guidelines on our web site or download them to your machine also from our web 
  1982. site.  These guidelines contain everything you need to know about writing an 
  1983. article for EDM/2. 
  1984.  
  1985. The editors can be reached at the following email addresses: 
  1986.  
  1987.      Larry Salomon - larry_salomon@iqpac.com (Internet). 
  1988.      Carsten Whimster - carsten_whimster@iqpac.com (Internet). 
  1989.  
  1990.  The following people contributed to this issue in one form or another (in 
  1991.  alphabetical order): 
  1992.  
  1993.      Stefan Ruck 
  1994.      Larry Salomon, Jr. 
  1995.      Brad Scharf 
  1996.      Carsten Whimster 
  1997.      Joe Wyatt 
  1998.      Gordon Zeglinski 
  1999.      Network distributors 
  2000.  
  2001.  Contributors - EDM/2 - Jul 1996 - Volume 4, Issue 6 
  2002.  
  2003.  
  2004. ΓòÉΓòÉΓòÉ 9.1. Stefan Ruck ΓòÉΓòÉΓòÉ
  2005.  
  2006. Stefan Ruck 
  2007.  
  2008. Stefan Ruck is working as a PC programer under DOS in a small software company. 
  2009. He got in touch with computers about 15 years ago at school and started 
  2010. programing BASIC on a Commodore VIC20.  He also did a little bit of assembler 
  2011. on this machine.  Later on he learned COBOL and structured programing on IBM 
  2012. mainframes.  Since about 6 years ago, he's been doing C programing on DOS PCs. 
  2013. After a short look at Windows 1 1/2 a year ago he started OS/2 programing in 
  2014. C++ in his spare time to learn a little bit more about GUIs and C++ and to see 
  2015. something new and different. 
  2016.  
  2017. He can be reached via CompuServe at 100664,1353 or via the Internet at 
  2018. 100664.1353@compuserve.com. 
  2019.  
  2020. Contributors - EDM/2 - Jul 1996 - Volume 4, Issue 6 
  2021.  
  2022.  
  2023. ΓòÉΓòÉΓòÉ 9.2. Larry Salomon, Jr. ΓòÉΓòÉΓòÉ
  2024.  
  2025. Larry Salomon Jr. 
  2026.  
  2027. Larry Salomon Jr.  has been developing OS/2 applications since version 1.1 in 
  2028. 1989.  He has written numerous applications, including the Scramble applet that 
  2029. was included in OS/2 versions 2.0-2.11, and the I-Brow, Magnify, and Screen 
  2030. Capture trio that has been distributed on numerous CD-ROMs. 
  2031.  
  2032. Larry is also the coauthor of the successful book, The Art of OS/2 2.1 C 
  2033. Programming (Wiley-QED).  Finally, he is the CEO/President of IQPac Inc.  which 
  2034. is responsible for the publication of EDM/2, and he is a frequent contributor 
  2035. to the publication. 
  2036.  
  2037. Larry can be reached electronically via the Internet at 
  2038. larry_salomon@iqpac.com. 
  2039.  
  2040. Contributors - EDM/2 - Jul 1996 - Volume 4, Issue 6 
  2041.  
  2042.  
  2043. ΓòÉΓòÉΓòÉ 9.3. Brad Scharf ΓòÉΓòÉΓòÉ
  2044.  
  2045. Brad Scharf 
  2046.  
  2047. Brad discovered computers while enrolled in a Chemistry B.Sc. program and soon 
  2048. switched to Computer Science.  He has been using OS/2 since the release of 
  2049. version 2.0, has used OS/2 exclusively since version 2.1, and is now in the 
  2050. process of teaching himself PM programming. 
  2051.  
  2052. Brad can be reached via the Internet at brad_scharf@iqpac.com. 
  2053.  
  2054. Contributors - EDM/2 - Jul 1996 - Volume 4, Issue 6 
  2055.  
  2056.  
  2057. ΓòÉΓòÉΓòÉ 9.4. Carsten Whimster ΓòÉΓòÉΓòÉ
  2058.  
  2059. Carsten Whimster 
  2060.  
  2061. Carsten is an undergraduate Computer Science student at the University of 
  2062. Waterloo.  He is currently in fourth year, and enjoying it immensely.  He uses 
  2063. Visual Age C++, Watcom C/C++ 10.0a and Watcom VX-REXX 2.0c.  Carsten is the 
  2064. author of some commandline utilities, and POV-Panel/2.  He is also a TEAM-OS/2 
  2065. member. 
  2066.  
  2067. You may reach Carsten... 
  2068.  
  2069. ...via email (Internet): 
  2070.  
  2071. carsten_whimster@iqpac.com 
  2072.  
  2073. ...via the World Wide Web: 
  2074.  
  2075. http://www.undergrad.math.uwaterloo.ca/~bcrwhims/ 
  2076.  
  2077. Please note the changed address and phone number 
  2078.  
  2079. ...via snail mail: 
  2080.  
  2081. Carsten Whimster
  2082. 43 Wilhelm Street, apt. 2
  2083. Kitchener, Ontario
  2084. Canada
  2085. N2H 5R9
  2086.  
  2087. ...via voice: 
  2088.  
  2089. (519)749-2391 
  2090.  
  2091. Contributors - EDM/2 - Jul 1996 - Volume 4, Issue 6 
  2092.  
  2093.  
  2094. ΓòÉΓòÉΓòÉ 9.5. Joe Wyatt ΓòÉΓòÉΓòÉ
  2095.  
  2096. Joe Wyatt 
  2097.  
  2098. Joe has been working in OS/2 since 1.3 and has programmed in Rexx on four 
  2099. different platforms.  Rexx projects have included elegant, complex systems in 
  2100. both VM and OS/2, operating system automation in MVS, and your basic "quick and 
  2101. dirty" tools in DOS.  He has recently mustered up the courage to jump into the 
  2102. world of consulting and self-employment.  (God help him.)  He makes his home in 
  2103. San Antonio, Texas with a wife and four children (along with 2 dogs, 1 cat, 1 
  2104. turtle, varying numbers of fish, and a rabbit). 
  2105.  
  2106. He can be reached via internet address joe_wyatt@iqpac.com for comments and 
  2107. criticisms. 
  2108.  
  2109. Contributors - EDM/2 - Jul 1996 - Volume 4, Issue 6 
  2110.  
  2111.  
  2112. ΓòÉΓòÉΓòÉ 9.6. Gordon Zeglinski ΓòÉΓòÉΓòÉ
  2113.  
  2114. Gordon Zeglinski 
  2115.  
  2116. Gordon Zeglinski is a freelance programmer/consultant who received his Master's 
  2117. degree in Mechanical Engineering with a thesis on C++ sparse matrix objects. 
  2118. He has been programming in C++ for 6 years and also has a strong background in 
  2119. FORTRAN.  He started developing OS/2 applications with version 2.0 . 
  2120.  
  2121. His current projects include a client/server communications program that 
  2122. utilitizes OS/2's features which has entered beta testing.  Additionally, he is 
  2123. involved in the development of a "real-time" automated vehicle based on OS/2 
  2124. and using C++ in which he does device driver development and designs the 
  2125. applications that comprise the control logic and user interface. 
  2126.  
  2127. He can be reached via the Internet at gordon_zeglinski@iqpac.com. 
  2128.  
  2129. Contributors - EDM/2 - Jul 1996 - Volume 4, Issue 6 
  2130.  
  2131.  
  2132. ΓòÉΓòÉΓòÉ 9.7. Network distributors ΓòÉΓòÉΓòÉ
  2133.  
  2134. Network Distributors 
  2135.  
  2136. These people are part of our distribution system to provide EDM/2 on networks 
  2137. other than the Internet.  Their help to provide access to this magazine for 
  2138. others is voluntary and we appreciate them a lot! 
  2139.  
  2140.      Paul Hethmon (phethmon@utk.edu) - Compuserve 
  2141.      Gess Shankar (gess@knex.mind.org) - Internet 
  2142.      Jason B. Tiller (PeerGynt@aol.com) - America On-line 
  2143.      Jesper Nielsen (jesniels@internet.dk) - Denmark BBS's 
  2144.  
  2145.  Gess is temporarily out of commission while he changes Internet domains. 
  2146.  
  2147.  If you would like to become a "network distributor", be sure to contact the 
  2148.  editors so that we can give you the credit you deserve! 
  2149.  
  2150.  Contributors - EDM/2 - Jul 1996 - Volume 4, Issue 6